package com.client.qiuqiu.crypto;
import android.util.Log;

import java.io.*;


public class RSA {
	long p,q,E,D,n,t;
	public RSA(long q,long p){
		this.p = p;
		this.q = q;
		this.n = q*p;
		this.t = (q-1)*(p-1);
		this.E = calculate_E(this.t);
		this.D = calculate_D(this.E, this.t);
	}
	
	public byte[] LongToBytes(long values) {//long ת 8bytes
	     byte[] buffer = new byte[8];
	     for (int i = 0; i < 8; i++) {
	          int offset = 64 - (i + 1) * 8;
	          buffer[i] = (byte) ((values >> offset) & 0xff);
	      }
	     return buffer;
	}
	
	public long BytesToLong(byte[] buffer) {//8bytes ת long
		long  values = 0;
	    for (int i = 0; i < 8; i++) {
	        values <<= 8;
	        values|= (buffer[i] & 0xff);
	    }
	    return values;
	} 
	
	public int prime(long pr) {//����Ƿ�������
		long j, i;
		j = (long) Math.sqrt(pr);
		for (i = 2;i <= j;i++) {
			if (pr % i == 0) {
				return 0;
			}	
		}
		return 1;
	}
	
	public long calculate_E(long t) {//���㹫Կ
		long i, flag;
		for (i = 2;i < t;i++) {
			if (t % i == 0) {//����Ƿ���ڹ�����
				continue;
			}
			flag = prime(i);//����Ƿ�������
			if (flag == 1) {
				return i;
			}
		}
		return 0;
	}
	
	public long calculate_D(long E, long T) {//����˽Կ
		long k = 1;
		while (true) {
			k = k + T;
			if (k % E == 0) {
				return (k / E);
			}
		}
	}
	
	public long encrypt(long E, long N, long msg) {//���ܣ������ַ���
		long pt, ct, key = E, k, j;
		pt = msg;
		pt = pt + 128;
		k = 1;
		for (j = 0;j < key;j++) {
			k = k * pt;
			k = k % N;
		}
		ct = k;
		return ct;
	}
	
	public long decrypt(long D, long N, long msg) {//���ܣ������ַ���
		long pt, ct, key = D, k, j;
		ct = msg;
		k = 1;
		for (j = 0;j < key;j++) {
			k = k * ct;
			k = k % N;
		}
		pt = k - 128;
		return pt;
	}
	
	public void encryption(String input_address, String output_address, String password) throws Exception {
		//���ܹ���
		InputStream f1 = new FileInputStream(input_address);
		OutputStream f2 = new FileOutputStream(output_address);
		byte[] key = AES.getPwd(password);
		Log.e("Key", String.valueOf(key));
		long or,med;
		int counter=0;
		while(counter<16) {
			or = key[counter];
			med=encrypt(E, n, or);//����
			byte[] en=LongToBytes(med);//��ת8bytes��ֹ���ݶ�ʧ
			f2.write(en);
			counter++;
		}
		int index=f1.available();
		byte[] content = new byte[index];
		int temp;
		int i=0;
		while(true) {
			temp = f1.read();
			if(temp==-1) {
				break;
			}
			content[i]=(byte)temp;
			i++;
		}
		//byte[] content = f1.readAllBytes();
		byte[] result = AES.encrypt(content, key);
		f2.write(result);
		f1.close();
		f2.close();
		System.out.println("Encryption finished.");
		return;
	}
	
	public void decryption(String input_address, String output_address) throws Exception {
		//���ܹ���
		InputStream f1 = new FileInputStream(input_address);
		OutputStream f2 = new FileOutputStream(output_address);
		long de,med;
		int counter=0;
		byte[] or = new byte[8];
		byte[] key = new byte[16];
		while(counter<16) {
			for(int i=0;i<8;i++) {
				or[i]=(byte) f1.read();
			}
			//or = f1.readNBytes(8);//8bytes��ȡ
			med=BytesToLong(or);//ת��long
			de=decrypt(D, n, med);//����
			key[counter]=(byte) de;
			counter++;
		}
		Log.e("Key2", String.valueOf(key));
		int index=f1.available();
		byte[] content = new byte[index];
		int temp;
		int i=0;
		while(true) {
			temp = f1.read();
			if(temp==-1) {
				break;
			}
			content[i]=(byte)temp;
			i++;
		}
		//byte[] content = f1.readAllBytes();
		byte[] result = AES.decrypt(content, key);
		f2.write(result);
		f1.close();
		f2.close();
		System.out.println("Decryption finished.");
		return;
	}
}
